package com.htthorizon.auth.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import com.htthorizon.auth.config.AuthConfig;
import com.htthorizon.common.core.context.SecurityContextHolder;
import com.htthorizon.common.core.utils.ip.IpUtils;
import com.htthorizon.system.api.domain.SysOperLog;
import com.htthorizon.system.api.exception.MaxUserException;
import com.htthorizon.system.api.exception.MultiTerminalLoginException;
import com.htthorizon.system.api.exception.UnAllowAccessTimeException;
import com.htthorizon.system.api.exception.UserUnExistException;
import com.htthorizon.auth.service.SysRecordLogService;
import com.htthorizon.common.core.constant.Constants;
import com.htthorizon.common.core.constant.SecurityConstants;
import com.htthorizon.common.redis.service.RedisService;
import com.htthorizon.system.api.RemoteLogService;
import com.htthorizon.system.api.RemoteUserService;
import com.sgcc.isc.core.orm.identity.User;
import com.sgcc.isc.service.adapter.factory.AdapterFactory;
import com.sgcc.isc.service.adapter.helper.IIdentityService;
import com.sgcc.isc.ualogin.client.IscServiceTicketValidator;
import com.sgcc.isc.ualogin.client.util.IscSSOResourceUtil;
import com.sgcc.isc.ualogin.client.vo.IscSSOUserBean;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.htthorizon.auth.form.LoginBody;
import com.htthorizon.auth.form.RegisterBody;
import com.htthorizon.auth.service.SysLoginService;
import com.htthorizon.common.core.domain.R;
import com.htthorizon.common.core.utils.JwtUtils;
import com.htthorizon.common.core.utils.StringUtils;
import com.htthorizon.common.security.auth.AuthUtil;
import com.htthorizon.common.security.service.TokenService;
import com.htthorizon.common.security.utils.SecurityUtils;
import com.htthorizon.system.api.model.LoginUser;

import java.util.*;

/**
 * token 控制
 * 
 * @author mark
 */
@RestController
@Slf4j
@CrossOrigin
public class TokenController
{
    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private AuthConfig authConfig;

    @Autowired
    private RemoteUserService userService;

    @Autowired
    private RemoteLogService remoteLogService;

    @Autowired
    private SysRecordLogService recordLogService;

    @PostMapping("login")
    public R<?> login(@RequestBody LoginBody form,HttpServletRequest request)
    {
        Enumeration<String> map = request.getHeaderNames();
        System.out.println("================================");
       while (map.hasMoreElements()){

           String s = map.nextElement();
           System.err.println(s);
           String header = request.getHeader(s);
           System.err.println(header);
       }
        System.out.println("================================");
        // 用户登录
        LoginUser userInfo=null;
        try{
            SecurityContextHolder.setUserName(form.getUsername());
           userInfo = sysLoginService.login(form.getUsername(), form.getPassword(),false);
            recordLogService.recordLogininfor(form.getUsername(), Constants.LOGIN_SUCCESS, "登录成功");
        }catch (UserUnExistException e){
           return R.fail("该账户已被禁用,请联系管理员");
        }

        // 获取登录token
        return R.ok(tokenService.createToken(userInfo));
    }

    @GetMapping("logout")
    public R<String> logout(HttpServletRequest request)
    {
        String token = SecurityUtils.getToken(request);

        if (StringUtils.isNotEmpty(token))
        {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            redisService.deleteObject("login_tokens:"+token);
            // 记录用户退出日志
            sysLoginService.logout(username);
        }
        return R.ok("推出成功");
    }

    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request)
    {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser))
        {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }

    @PostMapping("register")
    public R<?> register(@RequestBody RegisterBody registerBody)
    {
        // 用户注册
        sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
        return R.ok();
    }

    @ApiOperation(value = "登录接口")
    @PostMapping("loginSSO")
    public R<?> loginSSO(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String ticket = request.getParameter("ticket");
        if (StringUtils.isNotEmpty(ticket)) {
            IscServiceTicketValidator sv = new IscServiceTicketValidator();
            sv.setCasValidateUrl(authConfig.getSsoUrl() + "/serviceValidate");
            sv.setService(authConfig.getServiceUrl());
            sv.setServiceTicket(ticket);
            try {
                sv.validate();
            } catch (Exception e) {
                String user = sv.getUser();
                recordLogService.recordLogininfor("loginName", Constants.LOGIN_FAIL, "登录失败");
                log.error("ticket校验异常", e);
                return R.fail(e.getMessage());
            }
            if (sv.isAuthenticationSuccesful()) {
                String user = sv.getUser();
                if (StringUtils.isNotEmpty(user)) {
                    try {
                        IscSSOUserBean ssoUserBean = IscSSOResourceUtil.transferIscUserBean(user);
                        /*当前登录用户ID*/
                        String userid = ssoUserBean.getIscUserId();
                        System.out.println(userid);
                        /*当前登录用户账号*/
                        String loginName = ssoUserBean.getIscUserSourceId();
                        SecurityContextHolder.setUserName(loginName);
//                            LoginUser userInfo = sysLoginService.login(loginName, "Hndl-.2023", true);
//                        R<LoginUser> userInfoR = userService.getUserInfo(loginName, SecurityConstants.INNER);
//                        LoginUser loginUser = Optional.ofNullable(userInfoR).map(R::getData).orElse(new LoginUser());
                        LoginUser loginUser = sysLoginService.login(loginName, null,false);

                        recordLogService.recordLogininfor(loginName, Constants.LOGIN_SUCCESS, "登录成功");
                        this.addUserRecord();
                            return R.ok(tokenService.createToken(loginUser));

                    } catch (UserUnExistException e){

                        Map<String, List<String>> stringListMap = HttpUtil.decodeParams(user, "UTF-8");
                        Set<String> strings = stringListMap.keySet();

                        String name="";

                        for (String s : strings) {
                            JSONObject entries = new JSONObject(s);
                            name = entries.get("name").toString();
                        }
                        IIdentityService service = AdapterFactory.getIdentityService();
                        List<User> usersByName = service.getUsersByName(name);

                        User user1 = usersByName.get(0);
                        return R.ok(null,"新用户");
                    }  catch (MaxUserException e){
                        return R.ok(null,"已达最大会话数");
                    }catch (MultiTerminalLoginException e){
                        return R.ok(null,"多端登录");
                    }catch (UnAllowAccessTimeException e){
                        return R.ok(null,"未在指定时间段登录");
                    }catch (Exception e) {
                        log.error("获取用户异常", e);
                        return R.fail(e.getMessage());
                    }
                } else {
                    return R.fail("user 不存在");
                }
            } else {
                String user = sv.getUser();
                IscSSOUserBean ssoUserBean = IscSSOResourceUtil.transferIscUserBean(user);
                /*当前登录用户ID*/
                String userid = ssoUserBean.getIscUserId();
                /*当前登录用户账号*/
                String loginName = ssoUserBean.getIscUserSourceId();
                recordLogService.recordLogininfor(loginName, Constants.LOGIN_FAIL, "登录失败");
                log.error("ticket校验失败:{}", sv.getErrorMessage());
                return R.fail(sv.getErrorMessage());
            }
        } else {
            return R.fail("ticket 不存在");
        }
    }



    private void addUserRecord() {
            synchronized (TokenController.class){
                Integer userNumAll = redisService.getCacheObject("UserNumAll");
                Integer userNumToDay = redisService.getCacheObject("userNumToDay");
                if (Objects.isNull(userNumAll)){
                    userNumAll=1;
                    userNumToDay=1;
                    redisService.setCacheObject("UserNumAll",userNumAll);
                    redisService.setCacheObject("userNumToDay",userNumToDay);
                }else {
                    redisService.setCacheObject("UserNumAll", ++userNumAll);
                    redisService.setCacheObject("userNumToDay", ++userNumToDay);
                }
            }

    }


    @GetMapping("/authentication")
    public R<Boolean> authentication(@RequestParam("password") String password){
        // todo 二次认证还需跳转统一权限？
        return null;
    }

}
